package org.jeecg.modules.xxgx.fpgl.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.codec.Base64;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.common.util.MathUtil;
import org.jeecg.modules.common.util.XmlUtil;
import org.jeecg.modules.innerApi.common.responseDto.FileStreamRtn;
import org.jeecg.modules.innerApi.zhiYunApi.service.IZhiyunSkfpService;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.xxgx.common.enums.FplxdmEnum;
import org.jeecg.modules.xxgx.common.enums.HsbzEnum;
import org.jeecg.modules.xxgx.common.enums.QdbzEnum;
import org.jeecg.modules.xxgx.common.util.BarCodeUtils;
import org.jeecg.modules.xxgx.fpgl.entity.CsXxFpxx;
import org.jeecg.modules.xxgx.fpgl.entity.CsXxFpxxmx;
import org.jeecg.modules.xxgx.fpgl.service.ICsXxFpxxService;
import org.jeecg.modules.xxgx.fpgl.service.ICsXxFpxxmxService;
import org.jeecg.modules.xxgx.fpgl.vo.CsXxFpjfVO;
import org.jeecg.modules.xxgx.fpgl.vo.fpdy.*;
import org.jeecg.modules.xxgx.fpjf.service.ICsXxJfjlService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;


/**
 * @Description: 销项发票
 * @Author: jeecg-boot
 * @Date: 2023-09-21
 * @Version: V1.0
 */
@Api(tags = "销项发票")
@RestController
@RequestMapping("/xxgx/fpgl/csXxFpxx")
@Slf4j
public class CsXxFpxxKzController {
    @Autowired
    private ICsXxFpxxService csXxFpxxService;
    @Autowired
    private ICsXxFpxxmxService csXxFpxxmxService;

    @Autowired
    private IZhiyunSkfpService zhiyunSkfpService;

    @Autowired
    private ICsXxJfjlService csXxJfjlService;
    @Autowired
    private ISysDictService sysDictService;

    /**
     * 根据发票号码、发票代码查询发票信息
     *
     * @param fpdm
     * @param fphm
     * @param req
     * @return
     */
    @ApiOperation(value = "根据发票号码、发票代码查询发票信息", notes = "根据发票号码、发票代码查询发票信息")
    @GetMapping(value = "/getFpxxByfpdmhm")
    public Result<JSONObject> getFpxx(
            @ApiParam(value = "发票代码", required = true)
            @RequestParam(name = "fpdm", required = true) String fpdm,
            @ApiParam(value = "发票号码", required = true)
            @RequestParam(name = "fphm", required = true) String fphm,
            HttpServletRequest req) {
        List<CsXxFpxx> csXxFpxxes = csXxFpxxService.lambdaQuery().eq(CsXxFpxx::getFpdm, fpdm).eq(CsXxFpxx::getFphm, fphm).list();
        JSONObject data = new JSONObject();
        if (!csXxFpxxes.isEmpty()) {
            CsXxFpxx csXxFpxx = csXxFpxxes.get(0);
            List<CsXxFpxxmx> fpmxs = csXxFpxxmxService.lambdaQuery().eq(CsXxFpxxmx::getFromid, csXxFpxx.getId()).list();
            data = new JSONObject();
            data.put("fp", csXxFpxx);
            data.put("fpmx", fpmxs);
        } else {
            data.put("fp", null);
            data.put("fpmx", null);
        }
        return Result.OK("查询成功", data);
    }

    /**
     * 编辑
     *
     * @param
     * @return
     */
    @AutoLog(value = "销项发票-组装打印xml报文")
    @ApiOperation(value = "销项发票-组装打印xml报文", notes = "销项发票-组装打印xml报文")
    @RequestMapping(value = "/getFpxxDyxml", method = {RequestMethod.GET})
    public Result<String> getFpxxDyxml(
            @ApiParam(value = "发票ID", required = true)
            @RequestParam(name = "id", required = true)
            String id,
            @ApiParam(value = "打印类型1发票打印 2清单打印", required = false)
            @RequestParam(name = "dylx", required = false)
            String dylx) {

        //组装xml数据
        FpdyXmlBussiness xml = new FpdyXmlBussiness();
        FpdyXmlBody body = new FpdyXmlBody();
        xml.setBody(body);
        FpdyXmlBodyData bodyData = new FpdyXmlBodyData();
        body.setData(bodyData);

        FpdyXmlKpxx kpxx = new FpdyXmlKpxx();
        bodyData.setKpxx(kpxx);
        kpxx.setCount(1);

        List<FpdyXmlKpxx.Group> kpxxGroups = new ArrayList<>();

        int kpxxGroupXh = 1;
        //for(String id: ids){
        CsXxFpxx csXxFpxxEntity = csXxFpxxService.getById(id);
        if (csXxFpxxEntity == null) {
            return Result.error("未找到对应数据");
        }

        List<CsXxFpxxmx> fpxxmxList = csXxFpxxmxService.selectByMainId(id);

        FpdyXmlKpxx.Group kpxxGroup = new FpdyXmlKpxx.Group();
        BeanUtils.copyProperties(csXxFpxxEntity, kpxxGroup);
        kpxxGroup.setXh(kpxxGroupXh++);
        kpxxGroup.setKprq(DateUtils.formatDate(csXxFpxxEntity.getKprq(), "yyyyMMddHHmmss"));
        kpxxGroup.setJshj(MathUtil.add(csXxFpxxEntity.getHjje(), csXxFpxxEntity.getHjse()));


        if (QdbzEnum.Y.getValue().equals(csXxFpxxEntity.getQdbz())) {
            //清单
            FpdyXmlQdxm qdxm = new FpdyXmlQdxm();
            List<FpdyXmlQdxm.Group> qdxmGroups = new ArrayList<>();
            int qdxmGroupXh = 1;
            for (CsXxFpxxmx fpxxmx : fpxxmxList) {
                FpdyXmlQdxm.Group qdxmGroup = new FpdyXmlQdxm.Group();
                BeanUtils.copyProperties(fpxxmx, qdxmGroup);
                qdxmGroup.setXh(qdxmGroupXh++);
                qdxmGroup.setHsbz(csXxFpxxEntity.getHsbz());
                if (HsbzEnum.Y.getValue().equals(csXxFpxxEntity.getHsbz())) {
                    qdxmGroup.setDj(fpxxmx.getHsdj());
                    qdxmGroup.setJe(fpxxmx.getHsje());
                } else {
                    qdxmGroup.setDj(fpxxmx.getBhsdj());
                    qdxmGroup.setJe(fpxxmx.getBhsje());
                }

                qdxmGroups.add(qdxmGroup);
            }
            qdxm.setCount(fpxxmxList.size());
            qdxm.setGroup(qdxmGroups);
            kpxxGroup.setQdxm(qdxm);

            //费用项目 详见销货清单
            FpdyXmlFyxm fyxm = new FpdyXmlFyxm();
            List<FpdyXmlFyxm.Group> fyxmGroups = new ArrayList<>();
            FpdyXmlFyxm.Group fyxmGroup = new FpdyXmlFyxm.Group();
            //BeanUtils.copyProperties(fpxxmx, fyxmGroup);
            fyxmGroup.setSpmc("（详见销货清单）");
            fyxmGroup.setXh(1);
            fyxmGroup.setHsbz(csXxFpxxEntity.getHsbz());
               /*if (HsbzEnum.Y.getValue().equals(csXxFpxxEntity.getHsbz())) {
                   fyxmGroup.setJe(MathUtil.add(csXxFpxxEntity.getHjje(),csXxFpxxEntity.getHjse()));
               } else {
                   fyxmGroup.setJe(csXxFpxxEntity.getHjje());
               }*/
            fyxmGroup.setJe(csXxFpxxEntity.getHjje());
            fyxmGroup.setTaxje(csXxFpxxEntity.getHjse());

            fyxmGroups.add(fyxmGroup);

            fyxm.setCount(fpxxmxList.size());
            fyxm.setGroup(fyxmGroups);
            kpxxGroup.setFyxm(fyxm);
        } else {
            //费用项目
            FpdyXmlFyxm fyxm = new FpdyXmlFyxm();
            List<FpdyXmlFyxm.Group> fyxmGroups = new ArrayList<>();
            int fyxmGroupXh = 1;
            for (CsXxFpxxmx fpxxmx : fpxxmxList) {
                FpdyXmlFyxm.Group fyxmGroup = new FpdyXmlFyxm.Group();
                BeanUtils.copyProperties(fpxxmx, fyxmGroup);
                fyxmGroup.setXh(fyxmGroupXh++);
                fyxmGroup.setHsbz(csXxFpxxEntity.getHsbz());
                if (HsbzEnum.Y.getValue().equals(csXxFpxxEntity.getHsbz())) {
                    fyxmGroup.setDj(fpxxmx.getHsdj());
                    fyxmGroup.setJe(fpxxmx.getHsje());
                } else {
                    fyxmGroup.setDj(fpxxmx.getBhsdj());
                    fyxmGroup.setJe(fpxxmx.getBhsje());
                }

                fyxmGroups.add(fyxmGroup);
            }
            fyxm.setCount(fpxxmxList.size());
            fyxm.setGroup(fyxmGroups);
            kpxxGroup.setFyxm(fyxm);
        }
        kpxxGroups.add(kpxxGroup);
        //}
        kpxx.setGroup(kpxxGroups);

        String xmlStr = null;
        try {
            xmlStr = XmlUtil.beanToXml(xml, "gbk");
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
        log.debug(xmlStr);
        //转base64
        String xmlBase64 = Base64.encodeToString(xmlStr.getBytes());
        return Result.OK(xmlBase64);
    }

    @AutoLog(value = "销项发票-发票下载")
    @ApiOperation(value = "销项发票-发票下载", notes = "销项发票-发票下载")
    @RequestMapping(value = "/download", method = {RequestMethod.GET})
    public void download(@ApiParam(value = "发票ID", required = true)
                         @RequestParam(name = "id", required = true) String id,
                         @ApiParam(value = "类型 1:ofd 2:pdf 3:xml", required = true)
                         @RequestParam(name = "downflag", required = true) String downflag,
                         HttpServletResponse response) throws IOException {

        try {
            FileStreamRtn fileStreamRtn = csXxFpxxService.download(id, downflag);

            response.setContentType("application/octet-stream");
            InputStream in = fileStreamRtn.getFileStream();
            OutputStream out = response.getOutputStream();
            // 循环取出流中的数据
            byte[] b = new byte[100];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            in.close();
            out.close();
            response.flushBuffer();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            Result result = Result.error(e.getMessage());
            response.setContentType("application/json");
            response.getOutputStream().write(JSON.toJSONString(result).getBytes());
        }
    }

    @AutoLog(value = "销项发票-发票批量下载")
    @ApiOperation(value = "销项发票-发票批量下载", notes = "销项发票-发票批量下载")
    @RequestMapping(value = "/downloadBatch", method = {RequestMethod.POST})
    public void downloadBatch(@ApiParam(value = "发票信息ID数组", required = true) @RequestBody List<String> ids,
                              HttpServletResponse response) throws IOException {

        try {
            response.setContentType("application/octet-stream");
            ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(response.getOutputStream());
            zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded);
            for (String id : ids) {
                FileStreamRtn<CsXxFpxx> fileStreamRtn = csXxFpxxService.download(id, "2");

                CsXxFpxx csXxFpxx = fileStreamRtn.getData();
                String fileName = "";
                if (FplxdmEnum.sdzp.getValue().equals(csXxFpxx.getFplxdm()) || FplxdmEnum.sdpp.getValue().equals(csXxFpxx.getFplxdm())) {
                    fileName = csXxFpxx.getFphm();
                } else {
                    fileName = csXxFpxx.getFpdm() + "_" + csXxFpxx.getFphm();
                }
                fileName += ".pdf";
                ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(fileName);
                zipArchiveOutputStream.putArchiveEntry(zipArchiveEntry);

                InputStream in = fileStreamRtn.getFileStream();
                byte[] buffer = new byte[1024 * 5];
                int length = -1;//每次读取的字节大小。
                while ((length = in.read(buffer)) != -1) {
                    //把缓冲区的字节写入到 ZipArchiveEntry
                    zipArchiveOutputStream.write(buffer, 0, length);
                }
            }
            zipArchiveOutputStream.closeArchiveEntry();
            zipArchiveOutputStream.finish();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            Result result = Result.error(e.getMessage());
            response.setContentType("application/json");
            response.getOutputStream().write(JSON.toJSONString(result).getBytes());
        }
    }

    @AutoLog(value = "销项发票-获取发票交付二维码")
    @ApiOperation(value = "销项发票-获取发票交付二维码", notes = "销项发票-获取发票交付二维码")
    @RequestMapping(value = "/getFpjfewm", method = {RequestMethod.GET})
    public Result<String> getFpjfewm(
            @ApiParam(value = "发票ID", required = true)
            @RequestParam(name = "id", required = true)
            String id) {
        CsXxFpxx csXxFpxxEntity = csXxFpxxService.getById(id);
        if (csXxFpxxEntity == null) {
            return Result.error("未找到对应数据");
        }

        if(StringUtils.isBlank(csXxFpxxEntity.getFpjfurl())) {
            //生成发票交付短链接地址
            String fpjfUrl = csXxJfjlService.genFpjfShortUrl(csXxFpxxEntity);
            csXxFpxxEntity.setFpjfurl(fpjfUrl);
        }

        if(StringUtils.isNotBlank(csXxFpxxEntity.getFpjfurl())) {
            String qrcodeBase64 = BarCodeUtils.getImage2Base64String(BarCodeUtils.generateBarcodeWithoutWhite(csXxFpxxEntity.getFpjfurl(), null));
            return Result.OK(qrcodeBase64);
        } else {
            return Result.error("未设置发票交付二维码地址");
        }
    }

    @ApiOperation(value = "销项发票-获取发票交付信息", notes = "销项发票-获取发票交付信息")
    @RequestMapping(value = "/getFpjfxx", method = {RequestMethod.GET})
    public Result<CsXxFpjfVO> getFpjfxx(
            @ApiParam(value = "发票ID", required = true)
            @RequestParam(name = "id", required = true)
            String id,
            @ApiParam(value = "tenantId", required = true)
            @RequestParam(name = "tenantId", required = true)
            String tenantId) throws IOException {
        TenantContext.setTenant("0");//暂不使用参数中的tenantId，后面根据发票信息所属租户设置tenantId
        return csXxFpxxService.getBswj(id);
    }
}
